package com.tqjc.business.interactivewithscan.core.thread.crane;

import com.tqjc.business.interactivewithscan.consts.ActionEnum;
import com.tqjc.business.interactivewithscan.consts.CoordConstant;
import com.tqjc.business.interactivewithscan.core.data.AskData.AskData;
import com.tqjc.business.interactivewithscan.core.data.PointData.PointData;
import com.tqjc.business.interactivewithscan.core.thread.NormalThread;
import com.tqjc.business.interactivewithscan.entity.*;
import com.tqjc.business.interactivewithscan.service.AreaInfoService;
import com.tqjc.business.interactivewithscan.service.MaterialInfoService;
import com.tqjc.business.interactivewithscan.service.ScanDeviceDataService;
import com.tqjc.business.interactivewithscan.service.UfcDeviceInfoService;
import com.tqjc.business.interactivewithscan.service.impl.AreaInfoServiceImpl;
import com.tqjc.business.interactivewithscan.service.impl.MaterialInfoServiceImpl;
import com.tqjc.business.interactivewithscan.service.impl.ScanDeviceDataServiceImpl;
import com.tqjc.business.interactivewithscan.uils.*;
import com.tqjc.system.core.util.SpringUtils;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.NetSocket;
import kotlin.OverloadResolutionByLambdaReturnType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.RegEx;
import javax.annotation.Resource;
import java.sql.Timestamp;
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * @program: C20005_Xianggang_new
 * @description: 天车扫描线程
 * @author: Patienyon
 * @create: 2023-11-06 18:38
 **/
@Slf4j
//@Service("CraneScanThread")
public class CraneScanThread extends NormalThread {

    /**
     * 物料信息
     */
    private MaterialInfoService materialService = SpringUtils.getBean(MaterialInfoServiceImpl.class);

    /**
     * 库位信息
     */
//    private BWhlService whlService = SpringUtils.getBean(BWhlService.class);
    private AreaInfoService areaInfoService = SpringUtils.getBean(AreaInfoServiceImpl.class);
//    private BWhlCoordinatesService coordinatesService = SpringUtils.getBean(BWhlCoordinatesService.class);

    /**
     * 设备信息
     */
    private ScanDeviceDataService scanDeviceDataService = SpringUtils.getBean(ScanDeviceDataServiceImpl.class);


    @Resource
    UfcDeviceInfoService ufcDeviceInfoService;

    public CraneScanThread() {
        //绑定当前的设备信息
        this.device = scanDeviceDataService.getById(100012);
        log.error(device.toString());
        this.start();
    }

    @Override
    public void run() {
        while (true) {
            checkSocket();
            Integer sNum = 1;
            try {
//                AskData askData1 = new AskData();
//                askData1.setAskId("sss");
//                askData1.setAreaId("5");
//                askData1.setScanType(1);
//                addAskDataQue(askData1);
                //获取当前的请求列表
                final Queue<AskData> tmpAskData = getAskDataQue();
                //假设当前的请求列表有，循环准备开始获取抓点/放点
                while (!tmpAskData.isEmpty()) {
                    Integer num = 0;
                    AskData askData = tmpAskData.poll();

                    //读取当前的请求
                    //获取当前请求ID
                    String askId = askData.getAskId();
                    //获取当前的工作模式
                    String type = askData.getType();
                    //获取当前需要获取的区域ID
                    Long areaId = Long.parseLong(askData.getAreaId());
                    //所属跨
                    Integer scanId = askData.getScanType();

//                    根据不同的模式调取不同的方法

                    while (num < 3) {
                        //获取抓点

                        List<Coord> grabs = getGrabCoords(areaId, null, scanId);
                        System.out.println(grabs.toString());


//                        List<Coord> discharges = getDischargeCoords(areaId, null, scanId);
                        if (!grabs.isEmpty()) {
                            addResponseMap(askId, new PointData(true, "获取抓点成功", grabs, new Timestamp(System.currentTimeMillis())));
                            break;
                        }
                        num++;
                        if (num >= 3) {
                            addResponseMap(askId, new PointData(false, "获取抓点失败"));
                        }

                    }
                    askDataQue.poll();
                }

//                if(responseMap.containsKey("7")){
//                    System.out.println(responseMap.get("7"));
//                }

                Thread.sleep(1000);
                // 线程逻辑代码
            } catch (Exception e) {
                // 捕获线程异常
                e.printStackTrace();
                // 线程挂掉后，等待一段时间再重新启动
                try {
                    Thread.sleep(1000); // 可以根据需要调整等待时间
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
        }

    }

    @Override
    public synchronized Queue<AskData> getAskDataQue() {
        return askDataQue;
    }
    @Override
    public synchronized Map<String, PointData> getResponseMap() {
        return responseMap;
    }

    public synchronized void addAskDataQue(AskData askData) {
        this.askDataQue.add(askData);
    }

    public synchronized void addResponseMap(String askId, PointData pointData) {
        this.responseMap.put(askId, pointData);
    }

    @Override
    public void checkSocket() {
        do {
            //socket连接状态
            boolean is = socketClient == null || !socketClient.succeeded();
            log.error("当前连接状态{}", is);
            super.checkSocket();
            if (is) {
                log.error("当前连接成功");
                String actionResult = "";
                /* 查询设备状态 */
                DeviceCommandData<String> commandData = new DeviceCommandData(device, socketClient, ActionEnum.TC_Que_LidarStatus, String.class);
                actionResult = SocketCommandUtils.sendCommand(commandData);
                if (EmptyUtil.isEmpty(actionResult)) {
                    log.error("【" + device.getDeviceName() + "】执行【" + ActionEnum.TC_Que_LidarStatus.getActionName() + "】命令失败");
                    continue;
                }
                if (!actionResult.startsWith("fb LidarStatus ") || !actionResult.endsWith(" kp")) {
                    log.error("【" + device.getDeviceName() + "】执行【" + ActionEnum.TC_Que_LidarStatus.getActionName() + "】命令有点问题");
                    continue;
                }
                String[] status = actionResult.split(" ");
                if (status.length != 7 && (!"1".equals(status[2]) || !"1".equals(status[3]) || !"1".equals(status[4]) || !"1".equals(status[5]))) {
                    log.error("【" + device.getDeviceName() + "】执行【" + ActionEnum.TC_Que_LidarStatus.getActionName() + "】命令有点问题");
                    continue;
                }
                /* 激光雷达启动 */
                commandData = new DeviceCommandData(device, socketClient, ActionEnum.TC_Cmd_OpenLidar, String.class);
                actionResult = SocketCommandUtils.sendCommand(commandData);
                if (EmptyUtil.isEmpty(actionResult)) {
                    log.error("【" + device.getDeviceName() + "】执行【" + ActionEnum.TC_Cmd_OpenLidar.getActionName() + "】命令失败");
                    continue;
                }
                /* 激光雷达开始采集 */
                commandData = new DeviceCommandData(device, socketClient, ActionEnum.TC_Cmd_StartLidar, String.class);
                actionResult = SocketCommandUtils.sendCommand(commandData);
                if (EmptyUtil.isEmpty(actionResult)) {
                    log.error("【" + device.getDeviceName() + "】执行【" + ActionEnum.TC_Cmd_StartLidar.getActionName() + "】命令失败");
                    continue;
                }
                return;
            } else {
                return;
            }
        } while (true);
    }

    public String queryAreaResult(int type) {
        String actionResult = "";
        /* 废钢跨扫描结果 */
        if (type == 1) {
            DeviceCommandData<String> commandData = new DeviceCommandData(device, socketClient, ActionEnum.TC_Que_FGResult, String.class);
            actionResult = SocketCommandUtils.sendCommand(commandData);
            if (EmptyUtil.isEmpty(actionResult)) {
                log.error("【" + device.getDeviceName() + "】获取废钢跨扫描结果失败！");
            }
            return actionResult;
        }
        /* 炉渣跨扫描结果 */
        if (type == 2) {
            DeviceCommandData<String> commandData = new DeviceCommandData(device, socketClient, ActionEnum.TC_Que_FZResult, String.class);
            actionResult = SocketCommandUtils.sendCommand(commandData);
            if (EmptyUtil.isEmpty(actionResult)) {
                log.error("【" + device.getDeviceName() + "】获取炉渣跨扫描结果失败！");
            }
            return actionResult;
        }
        return actionResult;
    }

    private Map<Long, CoordDataEntity> grabCoords;

    private Map<Long, CoordDataEntity> dischargeCoords;

    public List<Coord> getDischargeCoords(Long areaId, String scanningResult, Integer scanMode) {
        System.err.println("【" + device.getDeviceName() + "】开始更新【" + areaId + "】的放料坐标");
        //TODO:更改点位生成方式
//        CoordDataEntity coordData = dischargeCoords.get(areaId);
        CoordDataEntity coordData = new CoordDataEntity();
//        if (coordData == null) {
//            coordData = new CoordDataEntity();
//        }

        //获取当前需要获取的区域
        AreaInfo areaInfo = areaInfoService.getById(areaId);

        //查询当前的物料
        long materialId = Long.parseLong(areaInfo.getStockMaterialNo());
        //查询当前的物料
        MaterialInfo material = materialService.getById(materialId);


        if (EmptyUtil.isEmpty(scanningResult)) {
            scanningResult = queryAreaResult(Integer.parseInt(areaInfo.getSpanNo()));
        } else {
            return null;
        }

//        System.out.println(scanningResult);
        // 扫描数据处理,拿到点位信息
        List<Coord> coordList = CoordinatesUtils.coordinatesScanningHandle(scanningResult, scanMode);
//        System.out.println(coordList.toString());
        //去除阴影
        CoordinatesUtils.fillShadows(coordList, CoordConstant.Maximum_Height_To_Top);
        // 获取库区四个顶点
        List<Coord> areas = new ArrayList<>();
        areas.add(new Coord(areaInfo.getIndexLeftTopX(), areaInfo.getIndexLeftTopY(), 0));
        areas.add(new Coord(areaInfo.getIndexRightBottomX(), areaInfo.getIndexRightBottomY(), 0));
        areas.add(new Coord(areaInfo.getIndexLeftTopX(), areaInfo.getIndexRightBottomY(), 0));
        areas.add(new Coord(areaInfo.getIndexRightBottomX(), areaInfo.getIndexLeftTopY(), 0));
        QuadrilateralVertex vertex = CoordinatesUtils.changeVertex(areas, CoordConstant.Boundary_Safe_Distance);
        // 筛选库区
        List<Coord> region = CoordinatesUtils.screenDesignationRegion(vertex, coordList);
//        System.out.println(region);
        CoordQuery query = new CoordQuery();
        query.setType(2);
        query.setThisDevice(ufcDeviceInfoService.getById(100004));
        query.setOtherDevice(ufcDeviceInfoService.getById(100005));

//        query.setFloorHeight(material.getLiftingHeight());
        query.setFloorHeight(200);

        // 一号先卸


        Coord discharge1 = CoordUtils.dischargeCoord(new ArrayList<>(region), vertex, query, true);
        Coord discharge2 = CoordUtils.dischargeCoord(new ArrayList<>(region), vertex, query, true);
        Coord discharge3 = CoordUtils.dischargeCoord(new ArrayList<>(region), vertex, query, true);
        Coord discharge4 = CoordUtils.dischargeCoord(new ArrayList<>(region), vertex, query, true);
        System.out.println(discharge1);
        System.out.println(discharge2);
        System.out.println(discharge3);
        System.out.println(discharge4);
        System.err.println("【" + device.getDeviceName() + "】结束更新【" + areaId + "】的放料坐标");
        return new ArrayList() {{
            add(discharge1);
            add(discharge2);
            add(discharge3);
            add(discharge4);
        }};

    }

    public List<Coord> getGrabCoords(Long areaOid, String scanningResult, Integer scanMode) {
        System.err.println("【" + device.getDeviceName() + "】开始更新【" + areaOid + "】的吸料坐标");
//        CoordDataEntity coordData = grabCoords.get(areaOid);
//        if (coordData == null) {
//            coordData = new CoordDataEntity();
//        }
//        BWhl coordinates = whlService.getById(areaOid);

        //获取当前需要获取的区域
        AreaInfo areaInfo = areaInfoService.getById(areaOid);
        //查询当前的物料
        long materialId = Long.parseLong(areaInfo.getStockMaterialNo());
        //查询当前的物料
        MaterialInfo material = materialService.getById(materialId);
        if (EmptyUtil.isEmpty(scanningResult)) {
            scanningResult = queryAreaResult(scanMode);
        }
        // 扫描数据处理,拿到点位信息
        List<Coord> coordList = CoordinatesUtils.coordinatesScanningHandle(scanningResult, scanMode);
        // 去除阴影
        CoordinatesUtils.removeShadows(coordList);
        // 获取库区四个顶点
        // 获取库区四个顶点
        List<Coord> areas = new ArrayList<>();
        areas.add(new Coord(areaInfo.getIndexLeftTopX(), areaInfo.getIndexLeftTopY(), 0));
        areas.add(new Coord(areaInfo.getIndexRightBottomX(), areaInfo.getIndexRightBottomY(), 0));
        areas.add(new Coord(areaInfo.getIndexLeftTopX(), areaInfo.getIndexRightBottomY(), 0));
        areas.add(new Coord(areaInfo.getIndexRightBottomX(), areaInfo.getIndexLeftTopY(), 0));
        QuadrilateralVertex vertex = CoordinatesUtils.changeVertex(areas, CoordConstant.Boundary_Safe_Distance);
        // 筛选库区
        List<Coord> region = CoordinatesUtils.screenDesignationRegion(vertex, coordList);
        // 一号先拿
        CoordQuery query = new CoordQuery();
        query.setType(1);
        query.setFloorHeight(200);
        query.setSeveral(20);
        UfcDeviceInfo firstCraneInfo = ufcDeviceInfoService.getById(100006);
        UfcDeviceInfo secondCraneInfo = ufcDeviceInfoService.getById(100007);
        SameSpanTianche tiancheInfo = TiancheUtils.settingTiancheInfo(ufcDeviceInfoService, scanMode, true);
        query.setThisDevice(tiancheInfo.getThisDevice());
        query.setOtherDevice(tiancheInfo.getOtherDevice());
        Coord grab1 = CoordUtils.grabCoord(new ArrayList<>(region), vertex, query);


        tiancheInfo = TiancheUtils.settingTiancheInfo(ufcDeviceInfoService, scanMode, false);
        query.setThisDevice(tiancheInfo.getThisDevice());
        query.setOtherDevice(tiancheInfo.getOtherDevice());
        query.setOtherCoord(grab1);
        Coord grab2 = CoordUtils.grabCoord(new ArrayList<>(region), vertex, query);


        //  二号先拿
        query.setOtherCoord(null);
        Coord grab3 = CoordUtils.grabCoord(new ArrayList<>(region), vertex, query);


        tiancheInfo = TiancheUtils.settingTiancheInfo(ufcDeviceInfoService, scanMode, true);
        query.setThisDevice(tiancheInfo.getThisDevice());
        query.setOtherDevice(tiancheInfo.getOtherDevice());
        query.setOtherCoord(grab3);
        Coord grab4 = CoordUtils.grabCoord(new ArrayList<>(region), vertex, query);

        System.err.println("【" + device.getDeviceName() + "】结束更新【" + areaOid + "】的吸料坐标");

        return new ArrayList() {{
            add(grab1);
            add(grab2);
            add(grab3);
            add(grab4);
        }};

    }


//    public void updateCoordinates() {
//        updateCoordinates(queryAreaResult(1), 1);
//        updateCoordinates(queryAreaResult(2), 2);
//    }

//    private void updateCoordinates(String scanningResult, int type) {
//        // 扫描数据处理,拿到点位信息
//        List<Coord> coordList = CoordinatesUtils.coordinatesScanningHandle(scanningResult, type);
//        CoordinatesUtils.removeShadows(coordList);
//        Result<List<BWhl>> result = whlService.queryList();
//        for (BWhl whl : result.getData()) {
//            Result<List<BWhlCoordinates>> listResult = whlService.coordinates(whl.getBWhloid());
//            List<BWhlCoordinates> coordinates = CoordinatesUtils.split25Pieces(coordList, listResult.getData(), whl);
//            coordinatesService.saveOrUpdateBatch(coordinates);
//        }
//    }

    public Map<Long, CoordDataEntity> getGrabCoords() {
        if (grabCoords == null) {
            grabCoords = new LinkedHashMap<>();
        }
        return grabCoords;
    }

    public Map<Long, CoordDataEntity> getDischargeCoords() {
        if (dischargeCoords == null) {
            dischargeCoords = new LinkedHashMap<>();
        }
        return dischargeCoords;
    }

    @Override
    public void heartbeat(DeviceSocketClient socketClient) {

        NetSocket socket = socketClient.getSocket();
        System.err.println("【" + device.getDeviceName() + "】首次发送心跳！");
        socket.write(Buffer.buffer("HB"));
        socketClient.getVertx().setPeriodic(1000, t -> {
            socket.write(Buffer.buffer("HB"));
        });
    }
}
